Skip to main content
Version: Next

JSON handling

The Navida App consumes a lot of JSON data from multiple sources, including aok-config, plugin-config, and API responses. While simple in theory, in practice it's a complex task—especially when handling edge cases like missing or invalid data.

As of today, there are two mechanisms in place to process JSON: kotlinx.serialization and Google’s Gson library. The former is widely used in the open-contract library, including all Backend API communication. On the other hand, the Navida plugins-repository revolves around Gson. This is due to the API exposed by PluginConfigManager, which delivers plugin-config as a string.

It's crucial to note that these two libraries handle Kotlin data classes differently—see commons/src/test/java/de/ey/commons/utils/TestJsonDecoding.kt for details. This leads to confusion among developers, unnecessary nullability, and app crashes due to uncaught exceptions.

To address these issues, new APIs have been added to PluginConfigManager. See below for details.

inline fun <reified T> getPluginConfigOrDefault(pluginId: String, default: T): T Returns a T object if parsing was successful, or default if any exception was thrown. This should be the primary way to work with plugin-configs.

inline fun <reified T> getPluginConfigOrNull(pluginId: String): T? Returns a T object if parsing was successful, or null otherwise. Use this when parsing failure needs to be handled separately.

Migration guide

As an example, consider AokSelectionRepositoryImpl. The following code:

override fun getAokSelectionPluginConfig(): AokSelectionPluginConfig? {
val envConfig = Gson().fromJson(
pluginConfigManager.getPluginConfig(AokSelectionPlugin.getInstance().identifier),
AokSelectionPluginConfig::class.java,
)
return envConfig
}

should be simplified to:

override fun getAokSelectionPluginConfig(): AokSelectionPluginConfig {
return pluginConfigManager.getPluginConfigOrDefault(
PluginIdentifier.AokSelection.identifier, AokSelectionPluginConfig()
)
}

At the same time, data classes representing config should be annotated with @Serializable:

@Serializable
data class AokSelectionPluginConfig(
@SerialName("aokId") val aokId: String = "",
....
)

defaultJson

To deal with any JSON data that is not coming from the PluginConfigManager, defaultJson static object is there to help.

TODO - debugging docs repo build pipeline